/**

 @Name：layuiAdmin 视图模块
 @Author：贤心
 @Site：http://www.layui.com/admin/
 @License：LPPL
    
 */

layui.define(['laytpl', 'layer'], function(exports) {
    var $ = layui.jquery,
        laytpl = layui.laytpl,
        layer = layui.layer,
        setter = layui.setter,
        device = layui.device(),
        hint = layui.hint()

        //对外接口
        ,
        view = function(id) {
            return new Class(id);
        }

        ,
        SHOW = 'layui-show',
        LAY_BODY = 'LAY_app_body'

        //构造器
        ,
        Class = function(id) {
            this.id = id;
            this.container = $('#' + (id || LAY_BODY));
        };

    //加载中
    view.loading = function(elem) {
        elem.append(
            this.elemLoad = $('<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon layui-icon-loading layadmin-loading"></i>')
        );
    };

    //移除加载
    view.removeLoad = function() {
        this.elemLoad && this.elemLoad.remove();
    };

    //清除 token，并跳转到登入页
    view.exit = function(callback) {
        //清空本地记录的 token
        layui.data(setter.tableName, {
            key: setter.request.tokenName,
            remove: true
        });

        //跳转到登入页
        //location.hash = '/user/login'; 
        callback && callback();
    };

    //Ajax请求
    view.req = function(options) {
        var that = this,
            success = options.success,
            error = options.error,
            request = setter.request,
            response = setter.response,
            debug = function() {
                return setter.debug ?
                    '<br><cite>URL：</cite>' + options.url :
                    '';
            };

        options.data = options.data || {};
        options.headers = options.headers || {};

        if (request.tokenName) {
            var sendData = typeof options.data === 'string' ?
                JSON.parse(options.data) :
                options.data;

            //自动给参数传入默认 token
            options.data[request.tokenName] = request.tokenName in sendData ?
                options.data[request.tokenName] :
                (layui.data(setter.tableName)[request.tokenName] || '');

            //自动给 Request Headers 传入 token
            options.headers[request.tokenName] = request.tokenName in options.headers ?
                options.headers[request.tokenName] :
                (layui.data(setter.tableName)[request.tokenName] || '');
        }

        delete options.success;
        delete options.error;

        return $.ajax($.extend({
            type: 'get',
            dataType: 'json',
            success: function(res) {
                var statusCode = response.statusCode;

                //只有 response 的 code 一切正常才执行 done
                if (res[response.statusName] == statusCode.ok) {
                    typeof options.done === 'function' && options.done(res);
                }

                //登录状态失效，清除本地 access_token，并强制跳转到登入页
                else if (res[response.statusName] == statusCode.logout) {
                    view.exit();
                }

                //其它异常
                else {
                    var error = [
                        '<cite>Error：</cite> ' + (res[response.msgName] || '返回状态码异常'), debug()
                    ].join('');
                    view.error(error);
                }

                //只要 http 状态码正常，无论 response 的 code 是否正常都执行 success
                typeof success === 'function' && success(res);
            },
            error: function(e, code) {
                var error = [
                    '请求异常，请重试<br><cite>错误信息：</cite>' + code, debug()
                ].join('');
                view.error(error);

                typeof error === 'function' && error(res);
            }
        }, options));
    };

    //弹窗
    view.popup = function(options) {
        var success = options.success,
            skin = options.skin;

        delete options.success;
        delete options.skin;

        return layer.open($.extend({
            type: 1,
            title: '提示',
            content: '',
            id: 'LAY-system-view-popup',
            skin: 'layui-layer-admin' + (skin ? ' ' + skin : ''),
            shadeClose: true,
            closeBtn: false,
            success: function(layero, index) {
                var elemClose = $('<i class="layui-icon" close>&#x1006;</i>');
                layero.append(elemClose);
                elemClose.on('click', function() {
                    layer.close(index);
                });
                typeof success === 'function' && success.apply(this, arguments);
            }
        }, options))
    };

    //异常提示
    view.error = function(content, options) {
        return view.popup($.extend({
            content: content,
            maxWidth: 300
                //,shade: 0.01
                ,
            offset: 't',
            anim: 6,
            id: 'LAY_adminError'
        }, options))
    };


    //请求模板文件渲染
    Class.prototype.render = function(views, params) {
        var that = this,
            router = layui.router();
        views = setter.views + views + setter.engine;

        $('#' + LAY_BODY).children('.layadmin-loading').remove();
        view.loading(that.container); //loading

        //请求模板
        $.ajax({
            url: views,
            type: 'get',
            dataType: 'html',
            data: {
                v: layui.cache.version
            },
            success: function(html) {
                html = '<div>' + html + '</div>';

                var elemTitle = $(html).find('title'),
                    title = elemTitle.text() || (html.match(/\<title\>([\s\S]*)\<\/title>/) || [])[1];

                var res = {
                    title: title,
                    body: html
                };

                elemTitle.remove();
                that.params = params || {}; //获取参数

                if (that.then) {
                    that.then(res);
                    delete that.then;
                }

                that.parse(html);
                view.removeLoad();

                if (that.done) {
                    that.done(res);
                    delete that.done;
                }

            },
            error: function(e) {
                view.removeLoad();

                if (that.render.isError) {
                    return view.error('请求视图文件异常，状态：' + e.status);
                };

                if (e.status === 404) {
                    that.render('../../../../../layuiadmin/template.tips/notfound');
                } else {
                    that.render('../../../../../layuiadmin/template.tips/err');
                }

                that.render.isError = true;
            }
        });
        return that;
    };

    //解析模板
    Class.prototype.parse = function(html, refresh, callback) {
        var that = this,
            isScriptTpl = typeof html === 'object' //是否模板元素
            ,
            elem = isScriptTpl ? html : $(html),
            elemTemp = isScriptTpl ? html : elem.find('*[template]'),
            fn = function(options) {
                var tpl = laytpl(options.dataElem.html()),
                    res = $.extend({
                        params: router.params
                    }, options.res);

                options.dataElem.after(tpl.render(res));
                typeof callback === 'function' && callback();

                try {
                    options.done && new Function('d', options.done)(res);
                } catch (e) {
                    console.error(options.dataElem[0], '\n存在错误回调脚本\n\n', e)
                }
            },
            router = layui.router();

        elem.find('title').remove();
        that.container[refresh ? 'after' : 'html'](elem.children());

        router.params = that.params || {};

        //遍历模板区块
        for (var i = elemTemp.length; i > 0; i--) {
            (function() {
                var dataElem = elemTemp.eq(i - 1),
                    layDone = dataElem.attr('lay-done') || dataElem.attr('lay-then') //获取回调
                    ,
                    url = laytpl(dataElem.attr('lay-url') || '').render(router) //接口 url
                    ,
                    data = laytpl(dataElem.attr('lay-data') || '').render(router) //接口参数
                    ,
                    headers = laytpl(dataElem.attr('lay-headers') || '').render(router); //接口请求的头信息

                try {
                    data = new Function('return ' + data + ';')();
                } catch (e) {
                    hint.error('lay-data: ' + e.message);
                    data = {};
                };

                try {
                    headers = new Function('return ' + headers + ';')();
                } catch (e) {
                    hint.error('lay-headers: ' + e.message);
                    headers = headers || {}
                };

                if (url) {
                    view.req({
                        type: dataElem.attr('lay-type') || 'get',
                        url: url,
                        data: data,
                        dataType: 'json',
                        headers: headers,
                        success: function(res) {
                            fn({
                                dataElem: dataElem,
                                res: res,
                                done: layDone
                            });
                        }
                    });
                } else {
                    fn({
                        dataElem: dataElem,
                        done: layDone
                    });
                }
            }());
        }

        return that;
    };

    //自动渲染数据模板
    Class.prototype.autoRender = function(id, callback) {
        var that = this;
        $(id || 'body').find('*[template]').each(function(index, item) {
            var othis = $(this);
            that.container = othis;
            that.parse(othis, 'refresh');
        });
    };

    //直接渲染字符
    Class.prototype.send = function(views, data) {
        var tpl = laytpl(views || this.container.html()).render(data || {});
        this.container.html(tpl);
        return this;
    };

    //局部刷新模板
    Class.prototype.refresh = function(callback) {
        var that = this,
            next = that.container.next(),
            templateid = next.attr('lay-templateid');

        if (that.id != templateid) return that;

        that.parse(that.container, 'refresh', function() {
            that.container.siblings('[lay-templateid="' + that.id + '"]:last').remove();
            typeof callback === 'function' && callback();
        });

        return that;
    };

    //视图请求成功后的回调
    Class.prototype.then = function(callback) {
        this.then = callback;
        return this;
    };

    //视图渲染完毕后的回调
    Class.prototype.done = function(callback) {
        this.done = callback;
        return this;
    };

    //对外接口
    exports('view', view);
});